package com.mjk.manager.magicapi.plugin.webservice.resource;

import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.StrUtils;
import com.mjk.manager.api.constns.ApiRequestType;
import com.mjk.manager.magicapi.core.core.config.MagicConfiguration;
import com.mjk.manager.magicapi.core.core.event.FileEvent;
import com.mjk.manager.magicapi.core.core.event.GroupEvent;
import com.mjk.manager.magicapi.core.core.service.AbstractMagicDynamicRegistry;
import com.mjk.manager.magicapi.core.core.service.MagicResourceService;
import com.mjk.manager.magicapi.core.core.service.MagicResourceStorage;
import com.mjk.manager.magicapi.plugin.webservice.model.WebServiceInfo;
import com.mjk.manager.magicapi.plugin.webservice.model.WebServiceParams;
import com.mjk.manager.magicapi.plugin.webservice.proxy.MagicWebServicePublish;
import groovy.lang.GroovyClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

public class WebServiceMagicDynamicRegistry extends AbstractMagicDynamicRegistry<WebServiceInfo> {

	public static final String SOAP_INTRTFACE = """
			package %s;\r
			import jakarta.jws.WebParam;\r
			import jakarta.jws.WebService;\r
			import com.mjk.common.web.getway.restful.prototal.ws.soap.annotation.BeeSoap;\r
			import com.mjk.common.web.getway.restful.prototal.ws.soap.annotation.BeeSoapMethod;\r
			import com.mjk.common.web.getway.restful.prototal.ws.soap.annotation.BeeSoapMethod.ResponseType;\r
			@WebService\r
			@BeeSoap(path = "%s")\r
			public interface %s {\r
			@BeeSoapMethod(reqType = %s ,rspType  = %s)\r
			public String testDrgs(%s);\r
			}""";

	private static final Logger logger = LoggerFactory.getLogger(WebServiceMagicDynamicRegistry.class);


	public WebServiceMagicDynamicRegistry(MagicResourceStorage<WebServiceInfo> magicResourceStorage) {
		super(magicResourceStorage);

	}

	@EventListener(condition = "#event.type == 'webservice'")
	public void onFileEvent(FileEvent event) {
		processEvent(event);
	}

	@EventListener(condition = "#event.type == 'webservice'")
	public void onGroupEvent(GroupEvent event) {
		processEvent(event);
	}

	@Override
	public boolean register(WebServiceInfo entity) {
		unregister(entity);
		return super.register(entity);
	}

	/**
	 * 发布webservice服务
	 *
	 * @param mappingNode
	 * @return
	 */
	@Override
	protected boolean register(MappingNode<WebServiceInfo> mappingNode) {
		WebServiceInfo entity = mappingNode.getEntity();
		MagicResourceService resource = MagicConfiguration.getMagicResourceService();
		String scriptName = resource.getScriptName(entity);
		buildInterface(entity, "/" + resource.getGroupPath(entity.getGroupId()) + "/" + entity.getPath(), entity);

		return true;
	}

	/**
	 * @param mappingNode
	 */
	@Override
	protected void unregister(MappingNode<WebServiceInfo> mappingNode) {
		BizLogger.info("webservice unregister");
		WebServiceInfo info = mappingNode.getEntity();
	}

	public Class<?> buildInterface(WebServiceInfo info, String path, WebServiceInfo entity) {
		List<String> params = new ArrayList<>();
		if(!CollectionUtils.isEmpty(info.getParams())) {
			for (WebServiceParams field : info.getParams()) {
				if (!ObjectUtils.isEmpty(field.getKey()))
					params.add("@WebParam(name=\"" + field.getKey() + "\")String " + field.getKey());
			}
		}
		String clazzName = "I" + StrUtils.toUpperCaseFirstOne(info.getPath()) + UUID.randomUUID().toString().replace("-", "");
		String iterface = String.format(SOAP_INTRTFACE, this.getClass().getPackage().getName(), path,
				clazzName, ApiRequestType.getType(info.getInType()), ApiRequestType.getType(info.getOutType()),
				StrUtils.join(params, ","));
		//BizLogger.info(iterface);
		GroovyClassLoader loader = new GroovyClassLoader(this.getClass().getClassLoader());
		Class clazz = loader.parseClass(iterface);
		MagicWebServicePublish.publish(clazz, path, loader, entity);
		return null;
	}
}
